Изучение кремниевого фотоумножителя

In [ ]:
import ROOT
import pandas as pd
import numpy as np
import plotly.graph_objects as go
import plotly.subplots as sub
In [ ]:
class my_KDE:

    def __init__(self, sample, bandwidth=1.0):
        self.sample = sample
        self.bandwidth = bandwidth

    def pdf(self, x):
        return [(1 / (2 * np.pi) ** 0.5) * np.exp(-(i - self.sample) ** 2 / (2 * self.bandwidth ** 2)).mean() / self.bandwidth for i in x]

    def pdf_max(self, x0, lam, eps):
        x1 = x0 + lam * (1 / (2 * np.pi) ** 0.5) * (-np.exp(-(x0 - self.sample) ** 2 / (2 * self.bandwidth ** 2)) \
            * (x0 - self.sample)).mean() / self.bandwidth ** 3
        while abs(x1 - x0) > eps:
            x0 = x1
            x1 = x0 + lam * (1 / (2 * np.pi) ** 0.5) * (-np.exp(-(x0 - self.sample) ** 2 / (2 * self.bandwidth ** 2)) \
                * (x0 - self.sample)).mean() / self.bandwidth ** 3
        return x1
In [ ]:
def print_err(a, a_err, vis=True):
    a = np.array([a]).flatten()
    a_err = np.array([a_err]).flatten()
    val = np.zeros_like(a)
    sig = np.zeros_like(a_err)
    for i in range(a.size):
        val[i] = np.round(a[i], decimals = round(1 * (np.trunc(np.log10(a_err[i]) < 0)) - np.trunc(np.log10(a_err[i]))))
        sig[i] = np.round(a_err[i], decimals = round(1 * (np.trunc(np.log10(a_err[i]) < 0)) - np.trunc(np.log10(a_err[i]))))
        if vis: print(val[i], '\pm', sig[i])
    return val, sig

Изучение шума SiPm и определение величины перенапряжения

In [ ]:
U = np.arange(25.5, 29.5, 0.5)
In [ ]:
for i in U:
    rdf = ROOT.RDataFrame('TD', 'data/{}.root'.format(int(i * 100)))
    data = pd.DataFrame(rdf.AsNumpy())
    A = [data['Par.A'][j] for j in range(data.shape[0])]
    chan = [data['Par.chan'][j] for j in range(data.shape[0])]
    tok = [data['Par.tok'][j] for j in range(data.shape[0])]
    type = [data['Par.type'][j] for j in range(data.shape[0])]
    user = [data['Par.user'][j] for j in range(data.shape[0])]
    I = data['Integral']
    pd.DataFrame({'A': A, 'chan': chan, 'tok': tok, 'type': type, 'user': user, 'I': I}).to_csv('data/{}.csv'.format(int(i * 100)), index=False)
In [ ]:
x = np.linspace(0, 1000, 2000)
In [ ]:
max1 = [69.34, 64.03, 90.92, 111.96, 134.09, 155.23, 179.88, 205.32]
In [ ]:
for num, val in enumerate(U):
    data = pd.read_csv('data/{}.csv'.format(int(val * 100)))
    mask = (data['chan'] == 53 * 64 + 16) * (data['type'] == 0)
    max1[num] = my_KDE(data['I'][mask], bandwidth=2.5 + num / 3).pdf_max(max1[num], 10, 0.000001)
In [ ]:
max2 = [117.33, 171.46, 216.39, 265.09, 306.74, 360.07, 403.32]
In [ ]:
for num, val in enumerate(U[1:]):
    data = pd.read_csv('data/{}.csv'.format(int(val * 100)))
    mask = (data['chan'] == 53 * 64 + 16) * (data['type'] == 0)
    max2[num] = my_KDE(data['I'][mask], bandwidth=2.5 + (num + 1) / 3).pdf_max(max2[num], 10, 0.00001)
In [ ]:
fig = sub.make_subplots(rows=U.size, cols=1, subplot_titles=['U={} В'.format(i) for i in U])

for num, val in enumerate(U):

    data = pd.read_csv('data/{}.csv'.format(int(val * 100)))
    mask = (data['chan'] == 53 * 64 + 16) * (data['type'] == 0)
    model = my_KDE(data['I'][mask], bandwidth=2.5 + num / 3)
    y = model.pdf(x)
    fig.add_traces(go.Scattergl(x=x, y=y, marker=dict(color='red'), showlegend=False), num + 1, 1)
    fig.add_traces(go.Histogram(x=data['I'][mask], xbins=dict(start=0, end=1000, size=4), marker=dict(color='blue', opacity=0.3),
                   autobinx=False, histnorm='probability density', showlegend=False), num + 1, 1)
    fig.add_traces(go.Scatter(y=model.pdf([max1[num]]), x=[max1[num]],
                              name='', marker=dict(size=7, color='green'), showlegend=False),
                              num + 1, 1)
    fig.add_annotation(x=max1[num], y=model.pdf([max1[num]])[0],
                       xref='x{}'.format(num + 1), yref='y{}'.format(num + 1),
                       text='max at ' + str(np.round(max1[num], decimals=4)),
                       showarrow=True, arrowhead=2, arrowsize=1, arrowwidth=2,
                       arrowcolor="#636363", ax=50, ay=-50, bordercolor="#c7c7c7", borderwidth=2, borderpad=4, bgcolor="#ff7f0e")
    if num != 0:
        fig.add_traces(go.Scatter(y=model.pdf([max2[num - 1]]), x=[max2[num - 1]],
                              name='', marker=dict(size=7, color='green'), showlegend=False),
                              num + 1, 1)
        fig.add_annotation(x=max2[num - 1], y=model.pdf([max2[num - 1]])[0],
                       xref='x{}'.format(num + 1), yref='y{}'.format(num + 1),
                       text='max at ' + str(np.round(max2[num - 1], decimals=4)),
                       showarrow=True, arrowhead=2, arrowsize=1, arrowwidth=2,
                       arrowcolor="#636363", ax=50, ay=-50, bordercolor="#c7c7c7", borderwidth=2, borderpad=4, bgcolor="#ff7f0e")

fig.update_layout(width=950, height=3000,
                  xaxis1=dict(range=(0, 1000)),
                  xaxis2=dict(range=(0, 1000)),
                  xaxis3=dict(range=(0, 1000)),
                  xaxis4=dict(range=(0, 1000)),
                  xaxis5=dict(range=(0, 1000)),
                  xaxis6=dict(range=(0, 1000)),
                  xaxis7=dict(range=(0, 1000)),
                  xaxis8=dict(range=(0, 1000)),
                  title='Поиск однопиксельных и двухпиксельных пиков ',
                  margin=dict(l=50, r=50, b=40, t=90))

fig.show('notebook')

При 25.5 В пики сливаются и искажают зависимость. Будем использовать только напряжения начиная с 26 В.

In [ ]:
max1 = max1[1:]
U = U[1:]
In [ ]:
fig = sub.make_subplots(rows=1, cols=2, subplot_titles=['Однопиксельные', 'Двухпиксельные'])

fig.add_traces(go.Scattergl(x=U, y=max1, mode='markers', marker=dict(color='blue'), name='Максимумы', legendgroup=1), 1, 1)
k1, err1 = np.polyfit(U, max1, deg=1, cov=True)
fig.add_traces(go.Scattergl(x=U, y=k1[0] * U + k1[1], mode='lines', marker=dict(color='red'), legendgroup=2, name='Аппроксимация'), 1, 1)

fig.add_traces(go.Scattergl(x=U, y=max2, mode='markers', marker=dict(color='blue'), showlegend=False, name='Максимумы', legendgroup=1), 1, 2)
k2, err2 = np.polyfit(U, max2, deg=1, cov=True)
fig.add_traces(go.Scattergl(x=U, y=k2[0] * U + k2[1], mode='lines', marker=dict(color='red'), legendgroup=2, showlegend=False, name='Аппроксимация'), 1, 2)

fig.update_layout(width=950, height=470,
                  legend=dict(orientation='v'),
                  title='Зависимость максимумов от напряжения напряжения',
                  xaxis1=dict(title='U, В'),
                  xaxis2=dict(title='U, В'),
                  margin=dict(l=50, r=50, b=40, t=90))

fig.show('notebook')
In [ ]:
D = np.array(k1[1] / k1[0] ** 2, -1 / k1[1])
U_break_1, U_break_err_1 = print_err(-k1[1] / k1[0], np.abs(D.dot(err1).dot(D)) ** 0.5, vis=False)
print('Напряжение пробоя по однопиксельным максимумам U = {} ± {} В'.format(U_break_1[0], U_break_err_1[0]))
Напряжение пробоя по однопиксельным максимумам U = 24.6 ± 0.4 В
In [ ]:
D = np.array(k2[1] / k2[0] ** 2, -1 / k2[1])
U_break_2, U_break_err_2 = print_err(-k2[1] / k2[0], np.abs(D.dot(err2).dot(D)) ** 0.5, vis=False)
print('Напряжение пробоя по двухпиксельным максимумам U = {} ± {} В'.format(U_break_2[0], U_break_err_2[0]))
Напряжение пробоя по двухпиксельным максимумам U = 24.7 ± 0.3 В
In [ ]:
U_break = (U_break_1[0] / U_break_err_1[0] ** 2 + U_break_2[0] / U_break_err_2[0] ** 2) / (1 / U_break_err_1[0] ** 2 + 1 / U_break_err_2[0] ** 2)
U_break_err = 1 / (1 / U_break_err_1[0] ** 2 + 1 / U_break_err_2[0] ** 2) ** 0.5
U_break, U_break_err = print_err(U_break, U_break_err, vis=False)
print('Напряжение пробоя U = {} ± {} В'.format(U_break[0], U_break_err[0]))
Напряжение пробоя U = 24.7 ± 0.2 В
In [ ]:
cr = []
for num, val in enumerate(U):
    data = pd.read_csv('data/{}.csv'.format(int(val * 100)))
    mask = (data['chan'] == 53 * 64 + 16) * (data['type'] == 0)
    cr.append(data['I'][mask].mean() / max1[num])
In [ ]:
fig = go.Figure()

fig.add_traces(go.Scattergl(x=U, y=cr, mode='markers', marker=dict(color='blue'), name='Crosstalk'))
k, err = np.polyfit(U, cr, deg=1, cov=True)
x = np.linspace(U.min(), U.max(), 100)
fig.add_traces(go.Scattergl(x=x, y=k[0] * x + k[1], mode='lines', marker=dict(color='red'), name='Аппроксимация'))

fig.update_layout(width=950, height=850,
                  legend=dict(orientation='v'),
                  title='Зависимость crosstalk от напряжения напряжения',
                  xaxis1=dict(title='U, В'),
                  xaxis2=dict(title='U, В'),
                  margin=dict(l=50, r=50, b=40, t=60))

fig.show('notebook')

Наблюдение сигналов от космических мюонов

In [ ]:
rdf = ROOT.RDataFrame('TD', 'data/million_hitov-4.root')
data = pd.DataFrame(rdf.AsNumpy())
I16 = [data['Par.I'][j][16] for j in range(data.shape[0])]
I17 = [data['Par.I'][j][17] for j in range(data.shape[0])]
I18 = [data['Par.I'][j][18] for j in range(data.shape[0])]
pd.DataFrame({'I[16]': I16, 'I[17]': I17, 'I[18]': I18}).to_csv('data/million_hitov-4.csv', index=False)
In [ ]:
data = pd.read_csv('data/million_hitov-4.csv')
In [ ]:
threshold = 1600
In [ ]:
fig = go.Figure()

fig.add_traces(go.Histogram(x=data['I[16]'][(data['I[17]'] > threshold) * (data['I[18]'] > threshold)],
                            xbins=dict(start=0, end=25000, size=1000), autobinx=False, opacity=0.7))

fig.update_layout(width=950, height=550,
                  title='Срабатывание 17 и 18',
                  margin=dict(l=50, r=50, b=40, t=60),
                  xaxis=dict(range=[0, 25000]))

fig.show('notebook')
In [ ]:
print('Зарегистрированно {} событий'.format(((data['I[17]'] > threshold) * (data['I[18]'] > threshold)).sum()))
Зарегистрированно 13 событий
In [ ]:
fig = go.Figure()

fig.add_traces(go.Histogram(x=data['I[17]'][(data['I[16]'] > threshold) * (data['I[18]'] > threshold)],
                            xbins=dict(start=0, end=25000, size=1000), autobinx=False, opacity=0.7))

fig.update_layout(width=950, height=550,
                  title='Срабатывание 16 и 18',
                  margin=dict(l=50, r=50, b=40, t=60),
                  xaxis=dict(range=[0, 25000]))

fig.show('notebook')
In [ ]:
print('Зарегистрированно {} событий'.format(((data['I[16]'] > threshold) * (data['I[18]'] > threshold)).sum()))
Зарегистрированно 32 событий
In [ ]:
fig = go.Figure()

fig.add_traces(go.Histogram(x=data['I[18]'][(data['I[17]'] > threshold) * (data['I[16]'] > threshold)],
                            xbins=dict(start=0, end=25000, size=1000), autobinx=False, opacity=0.7))

fig.update_layout(width=950, height=550,
                  title='Срабатывание 16 и 17',
                  margin=dict(l=50, r=50, b=40, t=60),
                  xaxis=dict(range=[0, 25000]))

fig.show('notebook')
In [ ]:
print('Зарегистрированно {} событий'.format(((data['I[16]'] > threshold) * (data['I[17]'] > threshold)).sum()))
Зарегистрированно 9 событий